package com.demo.component.sharding;


import io.shardingsphere.core.api.ShardingDataSourceFactory;
import io.shardingsphere.core.api.config.ShardingRuleConfiguration;
import io.shardingsphere.core.api.config.TableRuleConfiguration;
import io.shardingsphere.core.api.config.strategy.StandardShardingStrategyConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 配置sharding jdbc数据源
 * @author: Anjie
 * @date: 2018-06-07 19:40
 **/
@Configuration
@EnableJpaRepositories(
        basePackages = "com.demo.repository.sharding",
        entityManagerFactoryRef = "entityManagerFactoryBaoxianSharding",
        transactionManagerRef = "transactionManagerBaoxianSharding")
public class BaoxianShardingDataSourceConfiguration {

    @Resource
    private JpaProperties jpaProperties;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.baoxian")
    public DataSource dataSourceBaoxian1() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    DataSource baoxianShardingDataSource() throws SQLException {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
//        shardingRuleConfig.getTableRuleConfigs().add(getPolicyPaymentTableRuleConfiguration());
        shardingRuleConfig.getBindingTableGroups().add("insurance_policy_order_main, insurance_policy_payment");
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_no", new OrderNoShardingAlgorithm()));

        return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new HashMap<>(), null);
    }

    TableRuleConfiguration getOrderTableRuleConfiguration() {
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
        orderTableRuleConfig.setLogicTable("insurance_policy_order_main");
        orderTableRuleConfig.setActualDataNodes("dataSourceBaoxian1.insurance_policy_order_main_${0..9}${0..9}");
        return orderTableRuleConfig;
    }


    TableRuleConfiguration getPolicyPaymentTableRuleConfiguration() {
        TableRuleConfiguration policyPaymentRuleConfig = new TableRuleConfiguration();
        policyPaymentRuleConfig.setLogicTable("insurance_policy_payment");
        policyPaymentRuleConfig.setActualDataNodes("dataSourceBaoxian1.insurance_policy_payment_${0..9}${0..9}");
        return policyPaymentRuleConfig;
    }


    Map<String, DataSource> createDataSourceMap() {
        Map<String, DataSource> result = new HashMap<>(1, 1);
        result.put("dataSourceBaoxian1", dataSourceBaoxian1());
        return result;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBaoxianSharding(EntityManagerFactoryBuilder builder) throws SQLException {
        return builder
                .dataSource(baoxianShardingDataSource())
                .packages(new String[]{"com.demo.model.entity.baoxian"})
                .properties(jpaProperties.getHibernateProperties(baoxianShardingDataSource()))
                .persistenceUnit("baoxianSharding")
                .build();
    }


    @Bean
    PlatformTransactionManager transactionManagerBaoxianSharding(EntityManagerFactoryBuilder builder) throws SQLException {
        return new JpaTransactionManager(entityManagerFactoryBaoxianSharding(builder).getObject());
    }
}
